/*
 * Copyright (c) 2022 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <cstring>
#include <stdio.h>
#include <stdlib.h>  
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <net/if.h>
#include <unistd.h>
#include <fcntl.h>
#include "netdb.h"
#include "sys/types.h"
#include <sys/stat.h>
#include <sys/time.h>
#include "cJSON.h"
#include "base64.h"
#include "http.h"
#include "httpUrl.h"
#include "camera.h"
#include "log.h"

#include <fstream>  
#include <iostream>  
#include <string>   
#include <sstream>

using namespace std;

#define HEAD "POST /oauth/2.0/token?grant_type=client_credentials&client_id=%s&client_secret=%s HTTP/1.1\r\n"\
			 "Accept: */*\r\n"\
   			 "Content-Type: application/x-www-form-urlencoded\r\n"\
			 "Host: 139.9.102.131\r\n"\
			 "Cache-Control: no-store,no-cache\r\n"\
			 "Pragma: no-cache\r\n"\
			 "Content-Length: 0\r\n"\
			 "Connection: Close\r\n"\
			 "\r\n"
#define IP_ADDR "139.9.102.131"
#define PORT 80

#define LICENSE_HEAD "POST /rest/2.0/ocr/v1/accurate_basic?access_token=%s HTTP/1.1\r\n"\
					 "Content-Type: application/x-www-form-urlencoded\r\n"\
					 "Accept-Encoding: \r\n"\
					 "cache-control: no-cache\r\n"\
                     "Postman-Token: c963e8b2-75aa-4c2e-8c20-92d99fb118e1\r\n"\
	                 "User-Agent: PostmanRuntime/7.6.0\r\n"\
	                 "Accept: */*\r\n"\
                     "Host: 139.9.102.131\r\n"\
                     "accept-encoding: gzip, deflate\r\n"\
					 "content-length: %d\r\n"\
					 "Connection: keep-alive\r\n"\
                     "\r\n"

#define LICESE_IMG "image=%s"
static char s_value[32] = {0};
static int CreatSocketConnect(void)
{
	int sockd,rtn;
	struct hostent *ht;
	struct sockaddr_in srv_addr;
	struct in_addr **addr_list;
	
	sockd=socket(AF_INET,SOCK_STREAM,0);
    if(sockd<0){
        SAMPLE_ERROR("Do not open a socket.\n");
        return -1;
    }
    addr_list=(struct in_addr **)ht->h_addr_list;
    bzero(&srv_addr,sizeof(srv_addr));
    srv_addr.sin_family=AF_INET;
    srv_addr.sin_addr.s_addr=inet_addr(IP_ADDR);
    srv_addr.sin_port=htons(PORT);
    rtn=connect(sockd,(struct sockaddr *)(&srv_addr),sizeof(srv_addr));
	if(rtn<0){
		SAMPLE_ERROR("Can not connect to the web server, %s\n",inet_ntoa(srv_addr.sin_addr));
		close(sockd);
		return -1;
	}
	return sockd;
}

static std::string readFileIntoString(const std::string filename)
{
    ifstream ifile(filename.c_str());
    ostringstream buf;
    char ch;
    while(buf&&ifile.get(ch))
  	buf.put(ch);
    return buf.str();
}

static int GetToken(int sockFd, char *client_id, char *client_secret, char *token)
{
	int ret;
	char httpBuf[512] = {0};
	char recBuf[1024*6] = {0};
	char *recTokenSt,*recTokenEnd;
	
	sprintf(httpBuf, HEAD, client_id, client_secret);
	SAMPLE_INFO("will send -> %s", httpBuf);
	ret = send(sockFd,httpBuf,strlen(httpBuf),0);
	ret = recv(sockFd,recBuf,sizeof(recBuf),MSG_WAITALL);
	SAMPLE_INFO("recBuf->%s", recBuf);
	if (ret >0) {
		int tokenHeadOff = strlen("\"access_token\":\:");
		recTokenSt = strstr(recBuf, "\"access_token\"");
		recTokenSt = recTokenSt + tokenHeadOff;
		
		
		recTokenEnd = strstr(recTokenSt, ",\"scope\":");
		SAMPLE_INFO("recTokenEnd->%s", recTokenEnd);
		
		strncpy(token, recTokenSt , recTokenEnd - recTokenSt - 1);
		
	} else {
		
		SAMPLE_ERROR("recv GetToken\n");
		return -1;
	}
	return 0;
}

static int paraJson(char *data)
{
	char *use_c = strstr(data, "{\"words_result\"");
	SAMPLE_INFO("the use_c->%s\n", use_c);
	
	cJSON * root = NULL;
    cJSON * item = NULL;

    root = cJSON_Parse(use_c);     
    if (!root) {
        SAMPLE_ERROR("root is NULL");
        return -1;
    } else {
        item = cJSON_GetObjectItem(root, "words_result");
        if (!item) {
	        SAMPLE_ERROR("item is NULL");
	        return -1;
    	}
        SAMPLE_INFO("%s\n", cJSON_Print(item));
       
		int size = cJSON_GetArraySize(item);
		cJSON* tnode = NULL;
		
        tnode = cJSON_GetArrayItem(item, 0);
		if (!tnode) {
	        SAMPLE_ERROR("tnode is NULL");
	        return -1;
    	}
        
        SAMPLE_INFO("%s\n", cJSON_Print(tnode));
		cJSON* itemread=cJSON_GetObjectItem(tnode,"words");
		if (!tnode) {
	        SAMPLE_ERROR("itemread is NULL");
	        return -1;
    	}
		SAMPLE_INFO("arrayobjnum:  %s\n",itemread->valuestring );
		memset(s_value,0,sizeof(s_value));
		for(int i=0;itemread->valuestring[i]!='\0';i++) {
			SAMPLE_INFO("%x", itemread->valuestring[i]);
			s_value[i] = itemread->valuestring[i];
		}
		SAMPLE_INFO("s_value->%s", s_value);
    }
    return 0;
}

int getValue(char *buff)
{
	SAMPLE_INFO("ran that");
	if(s_value[0]=='\0'){
		SAMPLE_INFO("the s_value is NULL");
		return -1;
	}
	SAMPLE_INFO("ran that");	
	strcpy(buff, s_value);
	SAMPLE_INFO("ran that");
	return 0;
}



int dataForValue(void)
{
	
	if(s_value[0]=='\0'){
		SAMPLE_INFO("the s_value is NULL");
		return 0;
	}
	SAMPLE_INFO("s_value have data");	
	return -1;
}


static int GetLicense(int sockFd, char *token)
{
	char httpBuf[512] = {0};
	char revBuf[2048] = {0};

	char *ImgBuff = (char*) malloc(BURSIZE);
	memset(ImgBuff, 0, BURSIZE);
	char *LiceBuff = (char*) malloc(BURSIZE);
	memset(LiceBuff, 0, BURSIZE);
	char *ImgBuffUse = (char*) malloc(BURSIZE);
	memset(ImgBuffUse, 0, BURSIZE);
	int ret;
	
	string mys = readFileIntoString(IMG_PATH);
	std::string strFileContentBase64 = base64_encode(mys);
	SAMPLE_INFO("strFileContentBase64 lenght -> %d", strFileContentBase64.length());

	sprintf(ImgBuff, "%s", strFileContentBase64.c_str());
	SAMPLE_INFO("ImgBuff lenght ->%d", strlen(ImgBuff));
	urlencode(ImgBuff);
	SAMPLE_INFO("ImgBuff lenght -> %d", strlen(ImgBuff));

	sprintf(ImgBuffUse, LICESE_IMG,ImgBuff);
	sprintf(LiceBuff, LICENSE_HEAD, token, strlen(ImgBuffUse));
	SAMPLE_INFO("LiceBuff lenght ->%d", strlen(LiceBuff));
	strcat(LiceBuff, ImgBuffUse);
	ret = send(sockFd,LiceBuff,strlen(LiceBuff),0);
	SAMPLE_INFO("Send data, rtn code:%d",ret);
	
	memset(revBuf,0,sizeof(revBuf));
	ret = recv(sockFd, revBuf, sizeof(revBuf), MSG_WAITALL);
	if (ret <= 0) {
		SAMPLE_ERROR("recv");
		free(ImgBuff);
		free(LiceBuff);
		free(ImgBuffUse);
		return -1;
	} 
	SAMPLE_INFO("revBuf->%s", revBuf);
	ret = paraJson(revBuf);
	if (ret < 0) {
		SAMPLE_ERROR("paraJson");
		free(ImgBuff);
		free(LiceBuff);
		free(ImgBuffUse);
		return -1;
	}
	free(ImgBuff);
	free(LiceBuff);
	free(ImgBuffUse);
	return 0;
}

int http(void)
{
	int socket,ret;
	char token[256] = {0};
	SAMPLE_INFO("run that");
	memset(s_value, 0, sizeof(s_value));
	socket = CreatSocketConnect();
	if (socket < 0) {
		SAMPLE_ERROR("CreatSocketConnect");
		return -1;
	}


	ret = GetToken(socket, "NDgclUu5a74XKCCsjg9G8D9S", "3T1ze7NwGF0T7Xnnqtgm3hKqfFdqrD8Q", token);

	SAMPLE_INFO("the token ->%s", token);
	if (ret < 0){	
		SAMPLE_ERROR("GetToken");
		close(socket);
		return -1;
	}
	close(socket);
	
	socket = CreatSocketConnect();
	if (socket < 0) {
		SAMPLE_ERROR("CreatSocketConnect");
		return -1;
	}
	ret = GetLicense(socket, token);
	if (ret < 0){	
		SAMPLE_ERROR("GetLicense");
		close(socket);
		return -1;
	}
	close(socket);
	return 0;
}

